package com.yangchuang.openpicture.controller;

import com.yangchuang.openpicture.communication.ResponseMessage;
import com.yangchuang.openpicture.constant.FileUploadConstants;
import com.yangchuang.openpicture.constant.ThreadLocalConstants;
import com.yangchuang.openpicture.dto.*;
import com.yangchuang.openpicture.pojo.User;
import com.yangchuang.openpicture.service.OSSService;
import com.yangchuang.openpicture.service.UserService;
import com.yangchuang.openpicture.util.BaseContext;
import com.yangchuang.openpicture.util.RedisUtils;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.util.Map;

@Slf4j
@RestController
@RequestMapping("/user")
@RequiredArgsConstructor
@Tag(name = "用户服务", description = "处理用户相关的操作，如注册、登录和个人信息管理。")
public class UserController {

    private final UserService userService;
    private final OSSService ossService;
    private final RedisUtils redisUtils;

    @Operation(summary = "用户登录", description = "验证用户凭据并返回两个授权令牌。")
    @PostMapping("/login")
    public ResponseMessage<Map<String, Object>> login(@Valid @RequestBody UserLoginDTO userLoginDTO) {
        //email 和 password
        Map<String, Object> logindata = userService.login(userLoginDTO.getEmail(), userLoginDTO.getPassword());
        //这里 登录之后 返回两个token之外 还应该返回一些登录用户的拓明信息
        return ResponseMessage.success(logindata, "登陆成功");
    }

    @Operation(summary = "用户注册", description = "创建新用户账户。")
    @PostMapping("/register")
    public ResponseMessage<String> register(@Valid @RequestBody UserRegisterDTO userRegisterDTO) {
        log.info("新用户注册");
        userService.register(userRegisterDTO);
        return ResponseMessage.success(null, "用户注册成功");
    }


    @Operation(summary = "用户登出", description = "使当前用户的会话或令牌失效。")
    @PostMapping("/logout")
    public ResponseMessage<String> logout(@Valid @RequestBody UserLogoutDTO userLoginDTO) {
        log.info("用户退出登录");
        userService.logout(userLoginDTO);
        return ResponseMessage.success(null, "登出成功");
    }


    @Operation(summary = "更新个人信息", description = "允许用户更新他们的个人资料。")
    @PutMapping("/profile")
    public ResponseMessage<Void> updateProfile(@Valid @RequestBody UserUpdatePersonalInfoDTO userUpdatePersonalInfoDTO) {
        String currentUserId = (String) BaseContext.get(ThreadLocalConstants.USER_ID);
        log.info("用户 {} 更新个人信息", currentUserId);
        userService.updatePersonalInfo(currentUserId, userUpdatePersonalInfoDTO);
        return ResponseMessage.success(null, "个人信息更新成功");
    }

    //todo
    @Operation(summary = "获取个人信息", description = "获取当前登录用户的个人资料。")
    @GetMapping("/profile")
    public ResponseMessage<User> getProfile() {
        // 不接收参数 通过拦截器的校验 可以知道用户的id
        String id = (String) BaseContext.get(ThreadLocalConstants.USER_ID);
        log.info("请求用户个人信息：{}", id);
        User user = userService.getprofile(id);
        //TODO 返回用户的脱敏信息 即 重要的隐私字段不能返回 例如 password
        user.setPassword("");
        return ResponseMessage.success(user);
    }


    @PostMapping("/update-avatar")
    @Operation(summary = "用户更新头像", description = "更新用户头像并保存到OSS")
    public ResponseMessage<String> updateAvatar(@RequestParam("file") MultipartFile file) {
        // 1. 将文件上传到OSS ，获取其在OSS中唯一的ObjectName
        String objectName = ossService.uploadFile(file, FileUploadConstants.AVATAR);
        //2. 根据ObjectName 获得永久性的、公开可访问的文件URL。
        String signedUrl = ossService.getSignedUrlByObjectName(objectName);
        // 3. 更新用户头像URL
        String currentUserId = (String) BaseContext.get(ThreadLocalConstants.USER_ID);
        userService.updateAvatar(currentUserId, signedUrl);
        // 4. 返回给前端这个URL即可
        return ResponseMessage.success(signedUrl, "头像更新成功");
    }


    @Operation(summary = "忘记密码 - 重置密码", description = "使用邮箱和验证码重置密码")
    @PostMapping("/forget-password-reset")
    public ResponseMessage<String> resetPassword(
            @Valid @RequestBody UserForgetPasswordDTO userForgetPasswordDTO) {
        log.info("用户 {} 尝试重置密码", userForgetPasswordDTO.getEmail());
        userService.resetPassword(userForgetPasswordDTO);
        return ResponseMessage.success(null, "密码重置成功，请重新登录");
    }

    @Operation(summary = "刷新令牌", description = "使用刷新令牌获取新的访问令牌和刷新令牌")
    @PostMapping("/refresh-token")
    public ResponseMessage<Map<String, String>> refreshToken(@Valid @RequestBody UserRefreshTokenDTO userRefreshTokenDTO) {
        log.info("用户尝试刷新令牌，accessToken: {}", userRefreshTokenDTO.getAccesstoken());
        Map<String, String> newTokens = userService.refreshToken(userRefreshTokenDTO);
        return ResponseMessage.success(newTokens);
    }
    
}